package com.wsc.crawler.URLutils;

import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.EncoderException;
import org.apache.commons.codec.net.URLCodec;

import com.wsc.crawler.grabber.URLBeanQueue;

public class RefineURL {

	public static List<URL> list=null;
	
	static Logger log = Logger.getLogger(RefineURL.class.getName());
	
	public RefineURL(){
		
	}
	public static List<URL> DecodeURLs(List<URL> urlList){
		
		List<URL> refinedList=new ArrayList<URL>();
		for(int i=0; i<=urlList.size()-1 ; i++)
		{
			try {
				URL l=RefineURL.DecodeURL(list.get(i), "");
				refinedList.add(l);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			} catch (MalformedURLException e) {
				e.printStackTrace();
			}
		}
		return list;
		
	}
	
	// removeFragments() method removes fragments in URLs.
	
	public static URL removeFragments(URL url) throws MalformedURLException{
	
		String tmpurl=url.toString();
		
		// Get Index of # In URL
		
		int end=tmpurl.indexOf("#");
		
		// end is lessthan 0, means the supplied URL has no Fragment part.
		
		if(end <= 0)
		{
		// Return URL as it is.
			return url;
			
		}else{
		
		// if end > 0 then cut the #fragment part.
			
		tmpurl=tmpurl.substring(0, end);
		
		// Construct new URL, ehich has no fragment. 
		return (new URL(tmpurl));
		
		}
	}
	
	
	// removeFragments() method removes #fragments from strings (Or URLs in String Form ).
	
	public static String removeFragments(String url){
		String tmpurl=url.toString();
		int end=tmpurl.indexOf("#");
		if(end <= 0)
		{
		return url;	
		}else{
		tmpurl=tmpurl.substring(0, end);
		return  tmpurl ;
		}
	}
	
	public static List<String> removeFragments(List<String> urlList){
		
		// check whether urlList is empty.
		
		if(!urlList.isEmpty()){
			
			List<String> tmplist = new ArrayList<String>();
			
			// Get each URL From urlList
			
			for (String url : urlList){
			
				// for each url remove fragment
				String refinedURL = removeFragments(url); 
				
				// Add Refined URL to tmpList.
				tmplist.add(refinedURL);
			}
			
			// Return tmpList.
			return tmplist;
		}
		
		// This line will execute if if() condition fails.
		
		return null;
	}
	
	
	
	public static URL DecodeURL(URL url, String encodingType) throws UnsupportedEncodingException, MalformedURLException{
	
		String decodedurl=null;
		
		// Check encodingType parameter is empty, or null.
		
		if( encodingType==null || encodingType.isEmpty()){
		
		// If encodingtype is not specified, then decode URL with Default Encoding type UTF-8
			
			decodedurl=URLDecoder.decode(url.toString(), "UTF-8");
	
		}
		else{
		
		// If encoding type is specified then decode URL with given encodingType.
			
			decodedurl=URLDecoder.decode(url.toString(), encodingType);
			
		}
		
		// Finally return decoded URL.
		
		return (new URL(decodedurl));
	}
	
	
	/**
	 * 
	 * @param url
	 * @param encodingType
	 * @return
	 * @throws UnsupportedEncodingException
	 * @throws MalformedURLException
	 * 
	 * Returns a refined url
	 */
	public static URL refineURL(URL url,String encodingType) throws UnsupportedEncodingException, MalformedURLException{
		
		//decode url if it is already encoded
		
		URL refinedurl=RefineURL.DecodeURL(url, encodingType);

		// remove fragments if any.
	
		refinedurl=RefineURL.removeFragments(refinedurl);
		
		// now encode query part
		
		refinedurl = encodeQueryPart(refinedurl);
	
		//return refined url
	
		return refinedurl;
		}
	
	
	
	public static URLBeanQueue refinedURLs(URLBeanQueue urlList, String encodingType) throws UnsupportedEncodingException, MalformedURLException{
		
		URLBeanQueue refinedList=new URLBeanQueue();
		
		for(int i=0; i<=urlList.size()-1 ; i++)
		{
			/*
			 * If the encodingType is empty or null then consider default decoding method is UTF-8
			 * 
			 */
			// get a bean from queue. 
			URLBean bean=urlList.getURLBeanAt(i);
			
			//get URL from bean and Remove Fragment part.
			
			URL l=RefineURL.removeFragments(bean.getOriginalURL());
			
			
			l=RefineURL.refineURL(l, encodingType);
            
			//and replace old with new encoded url
			
			bean.setOriginalURL(l);
			
			// add to another queue
			
			refinedList.enqueue(bean);
		}
		
		//return new encoded url list.
		 
		return refinedList;
		
	}
	public static URL encodeQueryPart(URL url) throws MalformedURLException{
		 		
		// get path part of the URL supplied.
		
		String path=url.getFile();
		
		/*if the url has no path, or it is a web site home page, then add / to end of the url
		 *
		 *ex : http://ww.google.com  ==> http://www.google.com/
		 */

		URLCodec c=new URLCodec();
		
		if(!path.isEmpty()){
		
			try {
			
				
			 // First decode the url, this prevents url from double encoding, if the url already has encoded chars. 

			path=c.decode(path);

			/*
			 * now Encode the URL with basic encoding type UTF-8.
			 * And replace some common encodings with original chars.
			 */
		
			path=c.encode(path).replace("%2F", "/").replace("%3F", "?").replace("%3D", "=").replace("%3A", ":").replace("%26", "&");
			
			// Construct the URL with encoded query part.

			url=new URL(url.getProtocol()+"://"+url.getHost()+path);

			} catch (EncoderException e) {
			
				log.warning("Exception while Encoding Query part of URL.");
				
		} catch (DecoderException e) {
			
			log.warning("Exception while Encoding Query part of URL.");
		}
	}else{
		
	}
		
  return url;
	}
	
	/**
	 * 
	 * @param str
	 * @param c
	 * @param n
	 * @return
	 * 
	 * returns nth occurence of a char in given string
	 */
	public static int nthOccurrence(String str, char c, int n) {
	    int pos = str.indexOf(c, 0);
	    while (n-- > 0 && pos != -1)
	        pos = str.indexOf(c, pos+1);
	    return pos;
	}
}
